# 文件搜索与复制模块
# 用于从剪贴板读取值，搜索并复制文件或文件夹

import os
import shutil
import re
import pyperclip
import win32com.client
from datetime import datetime
import logging

# 配置日志
def setup_logger():
    """配置日志记录器"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler("file_search_copy.log"),
            logging.StreamHandler()
        ]
    )
    return logging.getLogger("FileSearchCopy")

logger = setup_logger()

class FileSearchCopyManager:
    """文件搜索与复制管理器类"""
    
    def __init__(self):
        """初始化文件搜索与复制管理器"""
        self.clipboard_content = []
        self.search_patterns = []
        logger.info("FileSearchCopyManager已初始化")
    
    def get_clipboard_values(self):
        """从剪贴板获取值并解析为列表"""
        try:
            content = pyperclip.paste()
            if not content:
                logger.warning("剪贴板为空")
                return False
            
            # 解析剪贴板内容，支持表格格式和列表格式
            if '\t' in content:  # 表格格式，使用制表符分隔
                lines = content.strip().split('\n')
                for line in lines:
                    cells = line.split('\t')
                    self.clipboard_content.extend([cell.strip() for cell in cells if cell.strip()])
            else:  # 列表格式，每行一个值
                self.clipboard_content = [line.strip() for line in content.strip().split('\n') if line.strip()]
            
            # 去重
            self.clipboard_content = list(set(self.clipboard_content))
            
            logger.info(f"从剪贴板获取到{len(self.clipboard_content)}个唯一值")
            return True
        except Exception as e:
            logger.error(f"获取剪贴板内容失败: {e}")
            return False
    
    def set_search_patterns(self, patterns=None):
        """设置搜索模式"""
        if patterns:
            self.search_patterns = patterns
        else:
            # 默认使用剪贴板内容作为搜索模式
            self.search_patterns = self.clipboard_content
        
        logger.info(f"设置了{len(self.search_patterns)}个搜索模式")
        return True
    
    def search_files(self, search_path, recursive=True):
        """在指定路径中搜索匹配的文件或文件夹"""
        if not os.path.exists(search_path):
            logger.error(f"搜索路径不存在: {search_path}")
            return []
        
        if not self.search_patterns:
            logger.warning("没有设置搜索模式")
            return []
        
        matched_items = []
        
        try:
            # 使用Windows搜索API进行更高效的搜索
            if os.name == 'nt':  # Windows系统
                try:
                    shell = win32com.client.Dispatch("Shell.Application")
                    search_folder = shell.NameSpace(search_path)
                    
                    for pattern in self.search_patterns:
                        logger.info(f"搜索模式: {pattern}")
                        # 这里简化处理，实际可以使用更复杂的Windows搜索API
                        
                        # 回退到Python原生搜索
                        for root, dirs, files in os.walk(search_path):
                            # 搜索文件
                            for file in files:
                                if self._match_pattern(file, pattern):
                                    file_path = os.path.join(root, file)
                                    matched_items.append((file_path, 'file'))
                                    logger.info(f"找到匹配文件: {file_path}")
                            
                            # 搜索文件夹
                            for dir in dirs:
                                if self._match_pattern(dir, pattern):
                                    dir_path = os.path.join(root, dir)
                                    matched_items.append((dir_path, 'folder'))
                                    logger.info(f"找到匹配文件夹: {dir_path}")
                            
                            if not recursive:
                                break
                except Exception as e:
                    logger.warning(f"Windows搜索API调用失败，使用Python原生搜索: {e}")
                    # 回退到Python原生搜索
                    for root, dirs, files in os.walk(search_path):
                        for pattern in self.search_patterns:
                            # 搜索文件
                            for file in files:
                                if self._match_pattern(file, pattern):
                                    file_path = os.path.join(root, file)
                                    matched_items.append((file_path, 'file'))
                                    logger.info(f"找到匹配文件: {file_path}")
                            
                            # 搜索文件夹
                            for dir in dirs:
                                if self._match_pattern(dir, pattern):
                                    dir_path = os.path.join(root, dir)
                                    matched_items.append((dir_path, 'folder'))
                                    logger.info(f"找到匹配文件夹: {dir_path}")
                        
                        if not recursive:
                            break
            else:
                # 非Windows系统使用Python原生搜索
                for root, dirs, files in os.walk(search_path):
                    for pattern in self.search_patterns:
                        # 搜索文件
                        for file in files:
                            if self._match_pattern(file, pattern):
                                file_path = os.path.join(root, file)
                                matched_items.append((file_path, 'file'))
                                logger.info(f"找到匹配文件: {file_path}")
                        
                        # 搜索文件夹
                        for dir in dirs:
                            if self._match_pattern(dir, pattern):
                                dir_path = os.path.join(root, dir)
                                matched_items.append((dir_path, 'folder'))
                                logger.info(f"找到匹配文件夹: {dir_path}")
                    
                    if not recursive:
                        break
            
            # 去重
            matched_items = list(set(matched_items))
            logger.info(f"总共找到{len(matched_items)}个匹配项")
            return matched_items
        except Exception as e:
            logger.error(f"搜索文件失败: {e}")
            return []
    
    def _match_pattern(self, name, pattern):
        """检查名称是否匹配模式"""
        try:
            # 支持部分匹配和正则表达式
            if pattern.startswith('regex:'):
                regex_pattern = pattern[6:]
                return bool(re.search(regex_pattern, name))
            else:
                # 不区分大小写的包含匹配
                return pattern.lower() in name.lower()
        except Exception as e:
            logger.error(f"匹配模式失败: {e}")
            return False
    
    def copy_items(self, matched_items, target_path, overwrite=False):
        """复制匹配的项目到目标路径"""
        if not os.path.exists(target_path):
            try:
                os.makedirs(target_path)
                logger.info(f"创建目标路径: {target_path}")
            except Exception as e:
                logger.error(f"创建目标路径失败: {e}")
                return False, 0
        
        if not matched_items:
            logger.warning("没有找到匹配的项目")
            return False, 0
        
        copied_count = 0
        failed_count = 0
        
        try:
            for item_path, item_type in matched_items:
                try:
                    # 生成目标路径，避免文件名冲突
                    target_item_path = self._get_unique_target_path(item_path, target_path)
                    
                    if item_type == 'file':
                        shutil.copy2(item_path, target_item_path)
                        logger.info(f"复制文件成功: {item_path} -> {target_item_path}")
                    else:  # folder
                        shutil.copytree(item_path, target_item_path)
                        logger.info(f"复制文件夹成功: {item_path} -> {target_item_path}")
                    
                    copied_count += 1
                except Exception as e:
                    logger.error(f"复制{item_path}失败: {e}")
                    failed_count += 1
            
            logger.info(f"复制完成: 成功{copied_count}个，失败{failed_count}个")
            return True, copied_count
        except Exception as e:
            logger.error(f"复制过程发生错误: {e}")
            return False, copied_count
    
    def _get_unique_target_path(self, source_path, target_dir):
        """生成唯一的目标路径，避免文件名冲突"""
        source_name = os.path.basename(source_path)
        target_path = os.path.join(target_dir, source_name)
        
        # 如果目标路径已存在，添加时间戳避免冲突
        if os.path.exists(target_path):
            base_name, ext = os.path.splitext(source_name)
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            target_path = os.path.join(target_dir, f"{base_name}_{timestamp}{ext}")
            
        return target_path
    
    def process_from_clipboard(self, search_path, target_path, recursive=True, overwrite=False):
        """一站式处理：从剪贴板读取值，搜索并复制文件"""
        logger.info("开始一站式处理")
        
        # 1. 从剪贴板获取值
        if not self.get_clipboard_values():
            return False, 0
        
        # 2. 设置搜索模式
        self.set_search_patterns()
        
        # 3. 搜索文件
        matched_items = self.search_files(search_path, recursive)
        if not matched_items:
            return False, 0
        
        # 4. 复制文件
        success, copied_count = self.copy_items(matched_items, target_path, overwrite)
        
        return success, copied_count

# 测试函数
def test_file_search_copy():
    """测试文件搜索与复制功能"""
    manager = FileSearchCopyManager()
    
    # 测试获取剪贴板内容
    print("测试获取剪贴板内容...")
    manager.get_clipboard_values()
    print(f"剪贴板内容: {manager.clipboard_content}")
    
    # 测试设置搜索模式
    print("\n测试设置搜索模式...")
    manager.set_search_patterns(["test", "example"])
    print(f"搜索模式: {manager.search_patterns}")
    
    # 提示用户测试搜索和复制功能
    print("\n注意：要测试完整功能，请确保剪贴板中有有效的搜索关键词")
    print("可以使用以下代码进行完整测试：")
    print("\nmanager = FileSearchCopyManager()")
    print("success, count = manager.process_from_clipboard('搜索路径', '目标路径')")
    print(f"复制结果: {'成功' if success else '失败'}, 复制了{count}个文件")

if __name__ == "__main__":
    test_file_search_copy()